package ss12.MobileColorIdentifier.Image;

import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;

import ss12.MobileColorIdentifier.ColorIdentifier;
import ss12.MobileColorIdentifier.database.DataBase;
import ss12.MobileColorIdentifier.speak.SpeakAndroid;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.Bundle;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.Gallery;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Toast;
import android.widget.Gallery.LayoutParams;

/**
 * 
 * @author Hanlong Chen
 *
 */
public class GPU extends Activity implements OnTouchListener,OnInitListener{
	// BMP image
	private Bitmap bitmap;

	// Image width and height
	private int width, height;

	// RGB color values
	private int r, g, b;

	// Target x and y coordinates
	private int x, y;

	// The input image in byte array format
	private byte[] imageData;

	// 
	private LinearLayout mLinearLayout;

	// To convert the hex to the name of the color
	private HexToStringConverter htsc;

	// Check if Language Data is available
	private static final int MY_DATA_CHECK_CODE=0;

	// To speak the name of the color
	private SpeakAndroid sp = null;

	// Keep it from running multiple times
	private boolean runnable = true;
	private Timer timer;

	@Override
	public void onCreate(Bundle savedInstanceState){
		super.onCreate(savedInstanceState);
		width = 0;
		height = 0;
		r = 0;
		g = 0;
		b = 0;
		x = 0;
		y = 0;		
		htsc = new HexToStringConverter();

		ImageView i = new ImageView(this);

		i.setAdjustViewBounds(true); // set the ImageView bounds to match the Drawable's dimensions
		i.setLayoutParams(new Gallery.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

		// Add the ImageView to the layout and set the layout as the content view
		mLinearLayout = new LinearLayout(this);
		mLinearLayout.addView(i);

		createBMP();
		i.setOnTouchListener(this);

		if(bitmap != null){
			i.setImageBitmap(bitmap);
		}
		setContentView(mLinearLayout);

		//check if the Language data is available
		Intent checkIntent = new Intent();
		checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
		startActivityForResult(checkIntent, MY_DATA_CHECK_CODE);
	}

	/** Called when the image is touched
	 */
	public boolean onTouch(View v, MotionEvent me){
		int ratio = height / 250;
		x = (int)me.getX() * ratio;
		y = (int)me.getY() * ratio;
		processImg();
		return true;
	}

	/** Main method that is called to process the image 
	 * @param imageData - the input image in byte array format
	 * @return the hex string value of the image center's average color
	 */
	private void processImg() {
		if(runnable) {
			runnable = false;
			avgColor();
			String colorName = htsc.getColorName(getHex());
			Toast.makeText(this, colorName, Toast.LENGTH_SHORT).show();
			sp.speakText(colorName);
			timer = new Timer();
			timer.schedule(new task(), 1000);
		}
	}

	/** To make runnable again
	 */
	class task extends TimerTask {
		public void run() {
			runnable = true;
		}
	}

	/** Creates a BMP image out of the input byte array
	 */
	private void createBMP() {
		imageData = ColorIdentifier.getByte();
		if(imageData != null) {
			bitmap = BitmapFactory.decodeByteArray(imageData, 0, imageData.length);
			width = bitmap.getWidth();
			height = bitmap.getHeight();
		} else {
			bitmap = Bitmap.createBitmap(300, 300, Bitmap.Config.RGB_565);
		}
	}

	/** Samples pixels in a checker board pattern over a region centered on x,y
	 *  to find the average color over the region
	 */
	private void avgColor() {
		if(x < 0 || x >= width || y < 0 || y >= height) {
			return;
		}

		// Half the height of the region to be sampled
		int sampleWidth = width/10;
		int sampleHeight = height/10;

		// Top left corner of region to be sampled
		int xStart = x - sampleWidth;
		int yStart = y - sampleHeight;

		// X and Y bounds of region
		int xBound = x + sampleWidth;
		int yBound = y + sampleHeight;

		// Ensure that region is within image bounds
		if(xBound >= width)
			xBound = width;
		else if(xStart < 0)
			xStart = 0;

		if(yBound >= height)
			yBound = height;
		else if(yStart < 0)
			yStart = 0;

		// Iterate over region
		for(int i = xStart; i < xBound; i += 2) {
			for(int j = yStart; j < yBound; j += 2) {
				int pixelColor = bitmap.getPixel(i, j);
				r += Color.red(pixelColor);
				g += Color.green(pixelColor);
				b += Color.blue(pixelColor);
			}
		}

		// Total number of pixels sampled
		int totalPixels = (xBound - xStart) * (yBound - yStart) / 4;

		// Get average RGB
		r = r/totalPixels;
		g = g/totalPixels;
		b = b/totalPixels;
	}

	/** Converts the RGB integers to hex strings and concatenates
	 * @return the hex output in int
	 */
	private int getHex() {
		String hexString = new String();
		String hex;

		hex = Integer.toHexString(r);
		if(hex.length() == 1)
			hex = "0" + hex;
		hexString += hex;

		hex = Integer.toHexString(g);
		if(hex.length() == 1)
			hex = "0" + hex;
		hexString += hex;

		hex = Integer.toHexString(b);
		if(hex.length() == 1)
			hex = "0" + hex;
		hexString += hex;

		return Integer.parseInt(hexString, 16);
	}

	/** Inherited method called when text-to-speech is initialized
	 * 
	 */
	public void onInit(int version) {
		if (version == TextToSpeech.SUCCESS) {
			// Set preferred language to US english.
			// Note that a language may not be available, and the result will indicate this.
			int result =  SpeakAndroid.mTts.setLanguage(Locale.US);
		}
	}

	/** Inherited method
	 * collect the status from the Intent
	 */
	protected void onActivityResult(
			int requestCode, int resultCode, Intent data) {
		if (requestCode == MY_DATA_CHECK_CODE) {
			if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
				// success, create the TTS instance
				SpeakAndroid.mTts = new TextToSpeech(this, this);
			} else {
				// missing data, install it
				Intent installIntent = new Intent();
				installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
				startActivity(installIntent);
			}
		}
	}

	@Override
	public void onDestroy() {
		// Don't forget to shutdown!
		if (SpeakAndroid.mTts != null) {
			SpeakAndroid.mTts.stop();
			SpeakAndroid.mTts.shutdown();
		}
		super.onDestroy();
	}

	@Override
	protected void onResume(){
		super.onResume();
	}

	@Override
	protected void onStop(){
		super.onStop();
	}

	@Override
	protected void onPause(){
		super.onPause();
	}
}
